#include "../include/Enemy.hh"
#include "../include/Player.hh"
#include <iostream>
#include <ctime>
#include <stdexcept>

namespace Game {
    // Constructor
    Enemy::Enemy(const std::string& name, unsigned h, unsigned a, unsigned d, unsigned exp)
        : name_(name), health_(h), attack_(a), defense_(d), expReward_(exp) {}

    // ICharacter: Check if alive
    bool Enemy::isAlive() const { 
        return health_ > 0; 
    }

    // ICharacter: Take damage
    void Enemy::takeDamage(int damage) {
        health_ = (damage > health_) ? 0 : health_ - damage;
    }

    // ICharacter: Attack target (with skill chance)
    void Enemy::attack(ICharacter& target) {
        if (skillCooldown_ <= 0 && rand() % 100 < 30) { // 30% chance to use skill
            lastActionLog_ = useSkill(target);
        } else {
            unsigned damage = calculateDamage(target.getDefense());
            target.takeDamage(damage);
            lastActionLog_ = name_ + " attacks! Deals " + std::to_string(damage) + " damage!";
        }
        if (skillCooldown_ > 0) skillCooldown_--;
    }

    // ICharacter: Name getter
    std::string Enemy::getName() const { 
        return name_; 
    }

    // ICharacter: Health getter
    unsigned Enemy::getHealth() const { 
        return health_; 
    }

    // ICharacter: Attack getter
    unsigned Enemy::getAttack() const { 
        return attack_; 
    }

    // ICharacter: Defense getter
    unsigned Enemy::getDefense() const { 
        return defense_; 
    }

    // ICharacter: Add item (enemies cannot hold items)
    void Enemy::addItem(Item* item) {
        delete item; // Enemies do not keep items
    }

    // ICharacter: Display inventory (empty for enemies)
    void Enemy::displayInventory() const {
        std::cout << name_ << " has no inventory!\n";
    }

    // ICharacter: Generate loot (override for specific drops)
    std::unique_ptr<Item> Enemy::generateDrop() const {
        if (name_ == "Dragon") {
            return std::make_unique<Item>("Dragon Scale", 0, 10, 10, Item::DRAGON_SCALE);
        } else if (rand() % 100 < 70) { // 70% drop chance
            switch (rand() % 5) {
                case 0: return std::make_unique<Item>("Health Potion", 20, 0, 0, Item::HEALTH_POTION);
                case 1: return std::make_unique<Item>("Sharp Sword", 0, 5, 0, Item::SWORD);
                case 2: return std::make_unique<Item>("Iron Shield", 0, 0, 5, Item::SHIELD);
                case 3: return std::make_unique<Item>("Poison Dagger", 0, 0, -3, Item::POISON_DAGGER);
                case 4: return std::make_unique<Item>("Magic Ring", 10, 3, 3, Item::MAGIC_RING);
                default: return nullptr;
            }
        }
        return nullptr;
    }

    // ICharacter: Clone enemy
    std::unique_ptr<ICharacter> Enemy::clone() const {
        return std::make_unique<Enemy>(*this);
    }

    // Enemy-specific: Get EXP reward
    unsigned Enemy::getExpReward() const { 
        return expReward_; 
    }

    // Enemy-specific: Apply enraged state
    void Enemy::applySpecialSkill() {
        if (health_ < 50 && !isEnraged_) {
            attack_ = static_cast<unsigned>(attack_ * 1.5);
            isEnraged_ = true;
            lastActionLog_ = name_ + " is enraged! Attack increased!";
        }
    }

    // Enemy-specific: Calculate final damage
    unsigned Enemy::calculateDamage(unsigned targetDefense) const {
        unsigned base = (isEnraged_) ? static_cast<unsigned>(attack_ * 1.5) : attack_;
        return (base > targetDefense) ? base - targetDefense : 0;
    }

    // Enemy-specific: Skill logic
    std::string Enemy::useSkill(ICharacter& target) {
        std::string log;

        // Dragon's Fire Breath
        if (name_ == "Dragon" && skillCooldown_ <= 0) {
            unsigned damage = attack_ * 2 - target.getDefense();
            damage = (damage > 0) ? damage : 0;
            target.takeDamage(damage);
            log = name_ + " unleashes Fire Breath! Deals " + std::to_string(damage) + " damage!";
            skillCooldown_ = 3;
        }

        // Skeleton's Heal
        else if (name_ == "Skeleton" && health_ < 30) {
            health_ += 20;
            log = name_ + " uses Bone Regeneration! Heals 20 HP!";
            skillCooldown_ = 2;
        }

        // Goblin Archer's Rapid Shot
        else if (name_ == "Goblin Archer" && rand() % 100 < 25) {
            unsigned damage = attack_ - target.getDefense();
            damage = (damage > 0) ? damage : 0;
            target.takeDamage(damage);
            log = name_ + " fires a rapid shot! Deals " + std::to_string(damage) + " damage!";
        }

        // Default attack if no skill
        else {
            unsigned damage = calculateDamage(target.getDefense());
            target.takeDamage(damage);
            log = name_ + " attacks! Deals " + std::to_string(damage) + " damage!";
        }

        lastActionLog_ = log;
        return log;
    }

    // Factory methods
    std::unique_ptr<Enemy> Enemy::createGoblin() {
        return std::make_unique<Enemy>("Goblin", 30, 8, 3, 30);
    }

    std::unique_ptr<Enemy> Enemy::createBoss() {
        return std::make_unique<Enemy>("Dragon", 200, 20, 10, 200);
    }

    std::unique_ptr<Enemy> Enemy::createSkeleton() {
        return std::make_unique<Enemy>("Skeleton", 70, 10, 5, 70);
    }

    std::unique_ptr<Enemy> Enemy::createGoblinArcher() {
        return std::make_unique<Enemy>("Goblin Archer", 40, 12, 4, 60);
    }

    // Get last action log
    const std::string& Enemy::getLastActionLog() const { 
        return lastActionLog_; 
    }
}